/**
 *
 * @author click
 */
package com.click.app.webapp.producers;

import com.click.app.model.CutDetail;
import com.click.app.model.Employee;
import com.click.app.model.PantDetail;
import com.click.app.model.PaymentsCut;
import com.click.app.model.PaymentsPant;
import com.click.app.service.CutDetailManager;
import com.click.app.service.EmployeeManager;
import com.click.app.service.PantDetailManager;
import com.click.app.service.PaymentsCutManager;
import com.click.app.service.PaymentsPantManager;
import com.click.app.webapp.reportObjects.EmployeesReportRow;
import java.io.Serializable;
import java.util.Date;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jfree.data.category.DefaultCategoryDataset;

import de.laures.cewolf.DatasetProduceException;
import de.laures.cewolf.DatasetProducer;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

public class ImageEmployeesReport implements DatasetProducer, Serializable {

    private static final Log log = LogFactory.getLog(PageViewCountData.class);
    private EmployeeManager employeeManager;
    private CutDetailManager cutDetailManager;
    private PantDetailManager pantDetailManager;
    private PaymentsCutManager paymentsCutManager;
    private PaymentsPantManager paymentsPantManager;

    // These values would normally not be hard coded but produced by
    // some kind of data source like a database or a file
    private final String[] categories = {"jan", "feb", "mar", "apr", "may", "jun", "jul", "aug", "sep", "oct", "nov", "dec"};
    private boolean years;
    private String type;
    private List<Employee> employees;
    private Date initDate;
    private Date endDate;
    private Map<Long, EmployeesReportRow> employeesReportRows;

    public ImageEmployeesReport(EmployeeManager employeeManager, CutDetailManager cutDetailManager, PantDetailManager pantDetailManager, PaymentsCutManager paymentsCutManager, PaymentsPantManager paymentsPantManager, List<Employee> employees, boolean years, String type, Date initDate, Date endDate) {
        this.employeeManager = employeeManager;
        this.cutDetailManager = cutDetailManager;
        this.pantDetailManager = pantDetailManager;
        this.paymentsCutManager = paymentsCutManager;
        this.paymentsPantManager = paymentsPantManager;
        this.employees = employees;
        this.years = years;
        this.type = type;
        this.initDate = initDate;
        this.endDate = endDate;
    }

    /**
     *  Produces some random data.
     */
    public Object produceDataset(Map params) throws DatasetProduceException {
        log.debug("producing data....");
        employeesReportRows = new HashMap<Long, EmployeesReportRow>();
        DefaultCategoryDataset dataset = new DefaultCategoryDataset() {

            protected void finalize() throws Throwable {
                super.finalize();
                log.debug(this + " finalized.");
            }
        };
        if (!years) {
            int month = initDate.getMonth();
            int year = initDate.getYear() + 1900;
            System.out.println("month: " + month + ", year: " + year);
            List<Integer> categoriesM = new ArrayList<Integer>();
            categoriesM.add(month * 10000 + year);
            int endMonth = endDate.getMonth();
            int endYear = endDate.getYear() + 1900;
            System.out.println("endmonth: " + endMonth + ", endyear: " + endYear);
            while (month != endMonth || year != endYear) {
                if (++month == 12) {
                    month = 0; 
                    year++;
                }
                System.out.println("month: " + month + ", year: " + year);
                categoriesM.add(month * 10000 + year);
            }
            if (type.equals("1")) {
                if (employees.get(0).isEmployeeCutter()) {
                    for (Employee e : employees) {
                        List<CutDetail> cutDetails = cutDetailManager.findByEmployeePeriod(e, initDate, endDate);

                        for (Integer i : categoriesM) {
                            int m = i / 10000;
                            int y = i % 10000;
                            Integer totalQuantity = 0;
                            List<CutDetail> cutDetailsRemove = new ArrayList<CutDetail>();
                            for (CutDetail cD : cutDetails) {
                                if (cD.getCutProcess().getEndDate().getMonth() == m) {
                                    totalQuantity = totalQuantity + cD.getQuantityGet();
                                    cutDetailsRemove.add(cD);
                                } else {
                                    break;
                                }
                            }
                            cutDetails.removeAll(cutDetailsRemove);
                            dataset.addValue(totalQuantity, e.getFullName() + " [" + e.getId() + "]", categories[m] + "-" + y);
                            EmployeesReportRow mrr = employeesReportRows.get(e.getId());
                            if (mrr == null) {
                                EmployeesReportRow newMrr = new EmployeesReportRow(e.getId(), e.getFullName());
                                newMrr.setCategory(categories[m] + "-" + y);
                                newMrr.setValue(totalQuantity);
                                employeesReportRows.put(e.getId(), newMrr);
                            } else {
                                mrr.setCategory(categories[m] + "-" + y);
                                mrr.setValue(totalQuantity);
                            }

                        }
                    }
                } else {
                    for (Employee e : employees) {
                        List<PantDetail> pantDetails = pantDetailManager.findByEmployeePeriod(e, initDate, endDate);

                        for (Integer i : categoriesM) {
                            int m = i / 10000;
                            int y = i % 10000;
                            Integer totalQuantity = 0;
                            List<PantDetail> pantDetailsRemove = new ArrayList<PantDetail>();
                            for (PantDetail pD : pantDetails) {
                                if (pD.getProcessDressmaker().getEndDate().getMonth() == m) {
                                    totalQuantity = totalQuantity + pD.getQuantityRealClothes();
                                    pantDetailsRemove.add(pD);
                                } else {
                                    break;
                                }
                            }
                            pantDetails.removeAll(pantDetailsRemove);
                            dataset.addValue(totalQuantity, e.getFullName() + " [" + e.getId() + "]", categories[m] + "-" + y);
                            EmployeesReportRow mrr = employeesReportRows.get(e.getId());
                            if (mrr == null) {
                                EmployeesReportRow newMrr = new EmployeesReportRow(e.getId(), e.getFullName());
                                newMrr.setCategory(categories[m] + "-" + y);
                                newMrr.setValue(totalQuantity);
                                employeesReportRows.put(e.getId(), newMrr);
                            } else {
                                mrr.setCategory(categories[m] + "-" + y);
                                mrr.setValue(totalQuantity);
                            }

                        }
                    }
                }
            } else {
                if (employees.get(0).isEmployeeCutter()) {
                    for (Employee e : employees) {
                        List<PaymentsCut> paymentsCuts = paymentsCutManager.findByEmployeePeriod(e, initDate, endDate);

                        for (Integer i : categoriesM) {
                            int m = i / 10000;
                            int y = i % 10000;
                            Double totalAmount = 0D;
                            List<PaymentsCut> paymentsCutsRemove = new ArrayList<PaymentsCut>();
                            for (PaymentsCut pC : paymentsCuts) {
                                if (pC.getDatePay().getMonth() == m) {
                                    totalAmount = totalAmount + pC.getAmount();
                                    paymentsCutsRemove.add(pC);
                                } else {
                                    break;
                                }
                            }
                            paymentsCuts.removeAll(paymentsCutsRemove);
                            dataset.addValue(totalAmount, e.getFullName() + " [" + e.getId() + "]", categories[m] + "-" + y);
                            EmployeesReportRow mrr = employeesReportRows.get(e.getId());
                            if (mrr == null) {
                                EmployeesReportRow newMrr = new EmployeesReportRow(e.getId(), e.getFullName());
                                newMrr.setCategory(categories[m] + "-" + y);
                                newMrr.setValue(totalAmount);
                                employeesReportRows.put(e.getId(), newMrr);
                            } else {
                                mrr.setCategory(categories[m] + "-" + y);
                                mrr.setValue(totalAmount);
                            }

                        }
                    }
                } else {
                    for (Employee e : employees) {
                        List<PaymentsPant> paymentsPants = paymentsPantManager.findByEmployeePeriod(e, initDate, endDate);

                        for (Integer i : categoriesM) {
                            int m = i / 10000;
                            int y = i % 10000;
                            Double totalAmount = 0D;
                            List<PaymentsPant> paymentsPantsRemove = new ArrayList<PaymentsPant>();
                            for (PaymentsPant pC : paymentsPants) {
                                if (pC.getDatePay().getMonth() == m) {
                                    totalAmount = totalAmount + pC.getAmount();
                                    paymentsPantsRemove.add(pC);
                                } else {
                                    break;
                                }
                            }
                            paymentsPants.removeAll(paymentsPantsRemove);
                            dataset.addValue(totalAmount, e.getFullName() + " [" + e.getId() + "]", categories[m] + "-" + y);
                            EmployeesReportRow mrr = employeesReportRows.get(e.getId());
                            if (mrr == null) {
                                EmployeesReportRow newMrr = new EmployeesReportRow(e.getId(), e.getFullName());
                                newMrr.setCategory(categories[m] + "-" + y);
                                newMrr.setValue(totalAmount);
                                employeesReportRows.put(e.getId(), newMrr);
                            } else {
                                mrr.setCategory(categories[m] + "-" + y);
                                mrr.setValue(totalAmount);
                            }

                        }
                    }
                }
            }
        } else {
            int year = initDate.getYear() + 1900;
            List<Integer> categoriesY = new ArrayList<Integer>();
            categoriesY.add(year);
            int endYear = endDate.getYear() + 1900;
            while (year != endYear) {
                categoriesY.add(++year);
            }
            if (type.equals("1")) {
                if (employees.get(0).isEmployeeCutter()) {
                    for (Employee e : employees) {
                        List<CutDetail> cutDetails = cutDetailManager.findByEmployeePeriod(e, initDate, endDate);

                        for (Integer i : categoriesY) {
                            Integer totalQuantity = 0;
                            List<CutDetail> cutDetailsRemove = new ArrayList<CutDetail>();
                            for (CutDetail cD : cutDetails) {
                                if (cD.getCutProcess().getEndDate().getYear() == i - 1900) {
                                    totalQuantity = totalQuantity + cD.getQuantityGet();
                                    cutDetailsRemove.add(cD);
                                } else {
                                    break;
                                }
                            }
                            cutDetails.removeAll(cutDetailsRemove);
                            dataset.addValue(totalQuantity, e.getFullName() + " [" + e.getId() + "]", i);
                            EmployeesReportRow mrr = employeesReportRows.get(e.getId());
                            if (mrr == null) {
                                EmployeesReportRow newMrr = new EmployeesReportRow(e.getId(), e.getFullName());
                                newMrr.setCategory(i + "");
                                newMrr.setValue(totalQuantity);
                                employeesReportRows.put(e.getId(), newMrr);
                            } else {
                                mrr.setCategory(i + "");
                                mrr.setValue(totalQuantity);
                            }
                        }
                    }
                } else {
                    for (Employee e : employees) {
                         List<PantDetail> pantDetails = pantDetailManager.findByEmployeePeriod(e, initDate, endDate);

                        for (Integer i : categoriesY) {
                            Integer totalQuantity = 0;
                            List<PantDetail> pantDetailsRemove = new ArrayList<PantDetail>();
                            for (PantDetail pD : pantDetails) {
                                if (pD.getProcessDressmaker().getEndDate().getYear() == i - 1900) {
                                    totalQuantity = totalQuantity + pD.getQuantityRealClothes();
                                    pantDetailsRemove.add(pD);
                                } else {
                                    break;
                                }
                            }
                            pantDetails.removeAll(pantDetailsRemove);
                            dataset.addValue(totalQuantity, e.getFullName() + " [" + e.getId() + "]", i);
                            EmployeesReportRow mrr = employeesReportRows.get(e.getId());
                            if (mrr == null) {
                                EmployeesReportRow newMrr = new EmployeesReportRow(e.getId(), e.getFullName());
                                newMrr.setCategory(i + "");
                                newMrr.setValue(totalQuantity);
                                employeesReportRows.put(e.getId(), newMrr);
                            } else {
                                mrr.setCategory(i + "");
                                mrr.setValue(totalQuantity);
                            }
                        }
                    }
                }
            } else {
                if (employees.get(0).isEmployeeCutter()) {
                    for (Employee e : employees) {
                        List<PaymentsCut> paymentsCuts = paymentsCutManager.findByEmployeePeriod(e, initDate, endDate);

                        for (Integer i : categoriesY) {
                            Double totalAmount = 0D;
                            List<PaymentsCut> paymentsCutsRemove = new ArrayList<PaymentsCut>();
                            for (PaymentsCut pC : paymentsCuts) {
                                if (pC.getDatePay().getYear() == i - 1900) {
                                    totalAmount = totalAmount + pC.getAmount();
                                    paymentsCutsRemove.add(pC);
                                } else {
                                    break;
                                }
                            }
                            paymentsCuts.removeAll(paymentsCutsRemove);
                            dataset.addValue(totalAmount, e.getFullName() + " [" + e.getId() + "]", i);
                            EmployeesReportRow mrr = employeesReportRows.get(e.getId());
                            if (mrr == null) {
                                EmployeesReportRow newMrr = new EmployeesReportRow(e.getId(), e.getFullName());
                                newMrr.setCategory(i + "");
                                newMrr.setValue(totalAmount);
                                employeesReportRows.put(e.getId(), newMrr);
                            } else {
                                mrr.setCategory(i + "");
                                mrr.setValue(totalAmount);
                            }
                        }
                    }
                } else {
                    for (Employee e : employees) {
                        List<PaymentsPant> paymentsPants = paymentsPantManager.findByEmployeePeriod(e, initDate, endDate);

                        for (Integer i : categoriesY) {
                            Double totalAmount = 0D;
                            List<PaymentsPant> paymentsPantsRemove = new ArrayList<PaymentsPant>();
                            for (PaymentsPant pC : paymentsPants) {
                                if (pC.getDatePay().getYear() == i - 1900) {
                                    totalAmount = totalAmount + pC.getAmount();
                                    paymentsPantsRemove.add(pC);
                                } else {
                                    break;
                                }
                            }
                            paymentsPants.removeAll(paymentsPantsRemove);
                            dataset.addValue(totalAmount, e.getFullName() + " [" + e.getId() + "]", i);
                            EmployeesReportRow mrr = employeesReportRows.get(e.getId());
                            if (mrr == null) {
                                EmployeesReportRow newMrr = new EmployeesReportRow(e.getId(), e.getFullName());
                                newMrr.setCategory(i + "");
                                newMrr.setValue(totalAmount);
                                employeesReportRows.put(e.getId(), newMrr);
                            } else {
                                mrr.setCategory(i + "");
                                mrr.setValue(totalAmount);
                            }
                        }
                    }
                }
            }
        }
        return dataset;
    }

    /**
     * This producer's data is invalidated after 5 seconds. By this method the
     * producer can influence Cewolf's caching behaviour the way it wants to.
     */
    public boolean hasExpired(Map params, Date since) {
        log.debug(getClass().getName() + "hasExpired()");
        return (System.currentTimeMillis() - since.getTime()) > 5000;
    }

    /**
     * Returns a unique ID for this DatasetProducer
     */
    public String getProducerId() {
        return "PageViewCountData DatasetProducer";
    }

    /**
     * @see java.lang.Object#finalize()
     */
    protected void finalize() throws Throwable {
        super.finalize();
        log.debug(this + " finalized.");
    }

    public Map<Long, EmployeesReportRow> getEmployeesReportRows() {
        return employeesReportRows;
    }
} 